import asyncio
import multiprocessing
from datetime import datetime

import uvicorn
from fastapi import FastAPI
from starlette.middleware.cors import CORSMiddleware
from starlette.requests import Request
from starlette.websockets import WebSocket, WebSocketDisconnect

import var
from config import websocket_ip, websocket_port, min_filter_frequency_default, max_filter_frequency_default
from handle_request import send_open_socket_server_cmd, close_socket_server, send_set_amplify_cmd, handle_disconnect, \
    init, handle_recent_data, handle_record_data, logger
from var import event_connect_start, websocket_queue, records_peak_queue, event_start_record, records_queue
from ws_manage import manager
import sys
import io

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


@app.middleware("http")
async def log_request_time(request, call_next):
    start_time = datetime.now()  # 记录请求开始时间
    response = await call_next(request)
    end_time = datetime.now()  # 记录请求结束时间
    processing_time = end_time - start_time  # 计算请求处理时间
    print(f"请求路径：{request.url.path}，请求开始时间:{start_time},处理时间：{processing_time}")
    return response


@app.get("/")
async def test():
    return {
        "code": 1,
    }


@app.post("/open")
async def open():
    # 如果连接上了， 且收到了消息。
    if var.event_socket_connected.is_set() and var.event_open_cmd_send.is_set():
        return {
            "code": 1,
            "msg": 'has already been opened'
        }
    send_open_socket_server_cmd()
    var.event_socket_connected.wait(2)
    var.event_open_cmd_send.wait(2)
    if var.event_socket_connected.is_set() and var.event_open_cmd_send.is_set():
        send_set_amplify_cmd(7)
        set_filter_params(min_filter_frequency_default, max_filter_frequency_default)
        return {
            "code": 1,
            "msg": 'ok'
        }
    elif not var.event_socket_connected.is_set():
        return {
            "code": -1,
            "msg": 'sensor connect failure'
        }
    else:
        return {
            "code": -1,
            "msg": 'sensor connect, but can not receive data'
        }


@app.post("/close")
async def close_breath():
    close_socket_server()
    # 清除记录信号量
    if event_start_record.is_set():
        event_start_record.clear()
    var.event_open_cmd_send.clear()
    handle_disconnect()
    return {
        "code": 1
    }


@app.post('/getRecent')
async def get_recent():
    data_arr = handle_recent_data()
    logger.info(f'recent arr len: ${len(data_arr)}')
    return {
        "code": 1,
        "data": data_arr
    }


@app.get("/record/start")
async def start_record():
    event_start_record.set()
    print(event_start_record.is_set())
    return {
        "code": 1,
    }


@app.get("/scan/start")
async def start_scan():
    var.event_scan_start.set()
    return {
        "code": 1,
    }


@app.get("/scan/end")
async def end_scan():
    var.event_scan_start.clear()
    return {
        "code": 1,
    }


@app.get("/record/end")
async def end_record():
    if event_start_record.is_set():
        var.event_scan_start.clear()
        var.event_start_record.clear()
        logger.info(f'end record qsize:{records_queue.qsize()}')
        arr = handle_record_data()
        return {
            "code": 1,
            "data": arr,
        }
    else:
        return {
            "msg": 'not open yet',
            "code": -1
        }


@app.get('/breathInfo')
async def get_breath_info():
    frequency = var.share_dict['q_breath_info']
    if frequency is not None:
        return {
            "code": 1,
            "data": frequency
        }
    else:
        return {
            "code": -1,
            "data": 0,
            "msg": 'not get yet'
        }


@app.post("/setFilter")
async def handle_filter(request: Request):
    request_body = await request.json()
    hi = request_body['hi']
    low = request_body['low']
    if hi == low:
        hi = low + 1
    set_filter_params(low, hi)
    # 在这里处理请求体
    return {
        "code": 1
    }


def set_filter_params(low, hi):
    var.share_dict['filter_hi'] = hi
    var.share_dict['filter_low'] = low


@app.post("/setAmplitude")
async def set_amplitude(request: Request):
    request_body = await request.json()
    amplitude = request_body['amplitude']
    send_set_amplify_cmd(amplitude)
    # 在这里处理请求体
    return {
        "code": 1
    }


@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    await manager.connect(websocket)
    print('连接成功')
    var.event_connect_start.set()
    try:
        while True:
            try:
                data = await asyncio.wait_for(websocket.receive_text(), timeout=0.5)
            except asyncio.TimeoutError:
                pass
            if websocket_queue.qsize() > 0:
                msg = websocket_queue.get()
                try:
                    await manager.send_personal_message(msg, websocket)
                except WebSocketDisconnect:
                    print('websocket disconnect')
                except Exception as e:
                    print('eee')
                    print(e)
            # await asyncio.sleep(0.5)
    except WebSocketDisconnect:
        print('连接断开')
        var.event_connect_start.clear()
        var.event_socket_connected.clear()
        var.event_open_cmd_send.clear()

        handle_disconnect()
        manager.disconnect(websocket)


def run_server():
    uvicorn.run(app, host=websocket_ip, port=websocket_port)


if __name__ == "__main__":
    # 处理打包为exe windows不支持多线程的问题
    multiprocessing.freeze_support()
    # 处理log乱码的问题
    sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
    sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')

    init()
    logger.info(f' v1.0 modify:  2024 - 2 - 27 ')

    run_server()
